
// Includes
//-----------------------------------------------------------------------------
#include "TargetBL_Config.h"
#include "TargetBL_Interface.h"
#include "tim.h"
#include "CRC.h"
#include <setjmp.h>
#include "flash_if.h"
#include "usart.h"
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------

//------------------------------------------
// 异常应答代码
//------------------------------------------
#define ILLEGAL_FUNCTION            0x01
#define ILLEGAL_DATA_ADDRESS        0x02
#define ILLEGAL_DATA_VALUE          0x03
#define SERVER_DEVICE_FAILURE       0x04
#define ACKNOWLEDGE                 0x05
#define SERVER_DEVICE_BUSY          0x06
#define MEMORY_PARITY_ERROR         0x08
#define GATEWAY_PATH_UNAVAILABLE    0x0A
#define GATEWAY_TARGET_NO_RESPONSE  0x0B
#define FLASH_WRITE_PROTECT_FAILURE 0x0C
#define FLASH_WRITE_FAILURE         0x0D


//-----------------------------------------------------------------------------
// Global Variables
//-----------------------------------------------------------------------------
#ifdef BL_OVERRIDE_PIN
//bit BL_Override_Pin = BL_OVERRIDE_PIN;
#endif



/* Private variables ---------------------------------------------------------*/
typedef  void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
extern const U8 TGT_BL_InfoBlock[TGT_BL_FW_INFOBLOCK_LENGTH];
//uchar  uart0_dr;                                 // uart1要发送长度
U8  Page_Buf[TGT_FLASH_PAGE_SIZE];
U8  rx_buf[TGT_BL_BUF_SIZE];
U8  rx_len = 0;
U8  server_address = 0x08;
U16 uart_timestamp;
bit user_app_ready = 0;

#define APP_MODE        0
#define BOOTLOADER_MODE 1

// Bit masks for the RSTSRC SFR
#define PORSF  0x02
#define FERROR 0x40


uchar REN0 = 1;                                  //允许接收
uchar  uart0_dr;                                 // uart1要发送长度
uchar  uart0_len = 0;                            // 已接收/或要发送长度
ushort uart0_timestamp;                          // 最后接收时间
uchar *uart0_tx_ptr;                             // 发送指针
bit uart0_rx_pending = 0;                        // uart0正在接收标志
bit uart0_tx_pending = 0;

//将多字节数转换为小端模式
U16 from_little_endian_16(U16 n)
{
    return (n << 8) | (n >> 8);
}
//将多字节数转换为小端模式
U32 from_little_endian_32(U32 n)
{
    return ((n << 24) & 0xFF000000) |
            ((n << 8 ) & 0x00FF0000) |
            ((n >> 8 ) & 0x0000FF00) |
            ((n >> 24) & 0x000000FF);
}

UU16 system_tick = {0};

ushort SystemTickLow()
{
    ushort tick = timer_counter_read(TIMER6);
    return tick;
}

ushort SystemTickHigh()
{
    uchar hi, lo;

    do
    {
        hi = system_tick.UU8[MSB];
        lo = system_tick.UU8[LSB];
    }
    while(hi != system_tick.UU8[MSB]);

    return (ushort)hi << 8 | lo;
}

ulong SystemTick()
{
    ushort hi, lo;
    do
    {
        hi = SystemTickHigh();
        lo = SystemTickLow();
    }
    while(hi != SystemTickHigh());

    return (ulong)hi << 16 | lo;
}

void Delay_Tick(ushort tick)
{
    ushort t = SystemTickLow();
    while((ushort)(SystemTickLow() - t) < tick);
}

void Delay_Tick_Loop(ulong tick)
{
    ulong t = SystemTick();
    //while(SystemTick() - t < tick)
        //Main_Loop();
}

// LED 闪烁
void LED_BLINK(ulong interval_us)
{
   static ulong stamp;
   if(SystemTick() - stamp > interval_us)
   {
       gpio_bit_toggle(LED_GPIO_Port,LED_Pin);
       stamp = SystemTick();
   }
}

void Read_Address(void)
{
    server_address = ((IO_S3() << 2)|(IO_S2() << 1)|(IO_S1() << 0)) + 0x10;
}

U16 timeout = FIVE_SEC;


bit Timeouts(void)
{
    if (timer_flag_get(TIMER6, TIMER_FLAG_UP) == SET)
    {
        timer_flag_clear(TIMER6, TIMER_FLAG_UP);
        if (timeout)
            --timeout;
    }
    return timeout == 0;
}

void ResetTimeouts()
{
    timeout = FIVE_SEC;
}

// uart0接收到了帧结束
bit Uart0_FrameEnded(void)
{
    return timer_flag_get(TIMER3, TIMER_FLAG_CH0);
}

void uart_send(uchar *data,uchar number)
{
    uart0_tx_pending = 1;
    uart0_tx_ptr = rx_buf;
    usart_interrupt_enable(USART2, USART_INT_TBE);
}

// uart receive
void uart_receive(void)
{
    while(1)
    {

        LED_BLINK(1000000);
         // 一帧消息接收完成
        if (uart0_rx_pending && Uart0_FrameEnded())
        {
            LED_BLINK(200000);
            uart0_rx_pending = 0;
            REN0 = 0;
            usart_interrupt_disable(USART2, USART_INT_RBNE);
            if (rx_buf[0] != server_address)
            {
                rx_len = 0;
                uart0_rx_pending = 0;
                REN0 = 1;
                usart_interrupt_enable(USART2, USART_INT_RBNE);
                continue;
            }
            if (user_app_ready && Timeouts())
            {
                NVIC_SystemReset();
            }

            ResetTimeouts();

            if (rx_len < 4)
            {
                rx_len = 0;
                uart0_rx_pending = 0;
                REN0 = 1;
                usart_interrupt_enable(USART2, USART_INT_RBNE);
                continue;
            }

            if (Get_Buf_CRC(rx_buf, rx_len-2) != from_little_endian_16(*(U16*)&rx_buf[rx_len-2]))
            {
                rx_len = 0;
                uart0_rx_pending = 0;
                REN0 = 1;
                usart_interrupt_enable(USART2, USART_INT_RBNE);
                continue;
            }

            if (rx_buf[0] == server_address || rx_buf[0] == 0)
            {
                return;
            }

        }

    }
}

void Response()
{
    // 计算CRC
    *(U16*)&rx_buf[rx_len] = from_little_endian_16(Get_Buf_CRC(rx_buf, rx_len));
    rx_len += 2;

    // 如果时间距离接收超过10ms, 不要发送
    //if (SystemTick() - uart_timestamp >= TEN_MS)
    //    return ;

    uart_send(rx_buf, rx_len);
}

void Exception_Response(U8 err)
{
    rx_buf[1] |= 0x80;
    rx_buf[2] = err;
    rx_len = 3;

    Response();
}

// 诊断
void Diagnose()
{
    U16 subfun = from_little_endian_16(*(U16*)&rx_buf[2]);    // 子功能代码

    switch(subfun)
    {
    case 0x00:        // 原样返回请求数据
    case 0x03:        // 改变ASCII结束符
        rx_len -= 2;
        Response();
        break;

    case 0x01:        // 复位通讯端口
        rx_len = 6;
        subfun = from_little_endian_16(*(U16*)&rx_buf[4]);
        Response();

        // 等等发送结束
        while(uart0_tx_pending);

        // 等等停止位发送结束
        Delay_Tick(100);

        // 重启
        NVIC_SystemReset();
        break;            // 运行不到此处

    default:        // 未实现或不正确的子功能代码
        Exception_Response(ILLEGAL_FUNCTION);
        break;
    }
}


uint32_t flash_sector,flash_erased_sector = CTL_SECTOR_NUMBER_11;
U8 Status1,Status2;
void Target_Init(void)
{
    U8 device_mode = BOOTLOADER_MODE;

   //---------------------------------------
   // Check the bootloader consition.
   //---------------------------------------
   // The Signature (in Flash) should be valid to allow application FW execution.
   // This is written at the end of the bootloading process by the bootloader.

    if(FLASH_Read(FLASH_SIG_ADDRESS) == SIG_BYTE && (U8)FLASH_Read(FLASH_DEVICE_CODE_ADDRESS) == DEVICE_CODE)
    {
       // user_app_ready = 1;
        device_mode = APP_MODE;
    }

    Status1 = rcu_flag_get(RCU_FLAG_FWDGTRST);
    Status2 = rcu_flag_get(RCU_FLAG_PORRST);
    //不是掉电复位和 发生独立看门狗复位
    if(Status2 != SET && Status1 == SET)
    {
        device_mode = BOOTLOADER_MODE;

    }
    rcu_all_reset_flag_clear();

    if (
#ifdef BL_OVERRIDE_PIN
            (BL_OVERRIDE_PIN)) //||
#endif
    {
        device_mode = BOOTLOADER_MODE;
    }

    // device_mode = APP_MODE;
    // device_mode = BOOTLOADER_MODE;
    // FLASH_If_WriteProtectionConfig(IO_S4());
    if (device_mode == APP_MODE)
    {
        // If not in BL Override, jump to application
        JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
        // Jump to user application
        Jump_To_Application = (pFunction) JumpAddress;
        //Initialize user application's Stack Pointer
        __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
        Jump_To_Application();
    }

    FLASH_If_Init();

    Read_Address();
}


//=============================================================================
// Main Routine
//=============================================================================
int Target_main(void)
{
    U16  index;
    U16  count;
    U8  *dst;
    U8  *src;
    U8  n;
    __IO uint32_t addr;
    uint32_t flash_sector;
    //-------------------------------------------
    // Main Loop
    //-------------------------------------------
    while(1)
    {
        uart_receive();

        switch(rx_buf[1])
        {
        case 0x08:      // 诊断
            Diagnose();
            break;

        case 0x10:      // 写多个RW-word
            index = from_little_endian_16(*(U16 *)&rx_buf[2]) - TGT_BUF_START_ADDR;
            count = from_little_endian_16(*(U16 *)&rx_buf[4]);

            // 检查地址和数量的正确性
            if (index >= TGT_FLASH_PAGE_SIZE >> 1   //2字节写入256
                    || index + count > TGT_FLASH_PAGE_SIZE >> 1)
                Exception_Response(ILLEGAL_DATA_ADDRESS);
            else if (rx_buf[6] != count << 1)
                Exception_Response(ILLEGAL_DATA_VALUE);
            else
            {
                count <<= 1;    // word => byte
                index <<= 1;
                dst = Page_Buf + index;
                src = &rx_buf[7];
                for (;count > 0; count--)
                {
                    *dst++ = *src++;
                }
                rx_len = 6;

                Response();
            }
            break;

        case 0x41:              // 读取程序Bootloader信息
            dst = &rx_buf[2];
            *dst++ = TGT_BL_FW_INFOBLOCK_LENGTH;
            for(n = 0; n < TGT_BL_FW_INFOBLOCK_LENGTH; ++n)
                *dst++ = TGT_BL_InfoBlock[n];
            rx_len = TGT_BL_FW_INFOBLOCK_LENGTH + 3;
            Response();
            break;

        case 0x42:              // 擦除FLASH页
            Flash_Key0 = rx_buf[6];
            Flash_Key1 = rx_buf[7];
            addr = from_little_endian_32(*(U32*)&rx_buf[2]);
            rx_len = 6;
            Response();

            flash_sector = GetSector(FLASH_BASE_ADDR + addr);

            //块已经擦除过，不再擦除，适用于从高地址向前擦除
            if(flash_sector >= flash_erased_sector)
                break;
            else
            {

                FLASH_If_Erase(flash_sector);
                flash_erased_sector = flash_sector;
            }
            Flash_Key0 = 0;
            Flash_Key1 = 0;
            break;

        case 0x43:        // 读取缓冲页CRC
            *(U16*)&rx_buf[2] = from_little_endian_16(Get_Buf_CRC(Page_Buf, TGT_FLASH_PAGE_SIZE));
            rx_len = 4;
            Response();
            break;

        case 0x44:        // 写入FLASH页
            Flash_Key0 = rx_buf[6];
            addr = from_little_endian_32(*(U32*)&rx_buf[2]);
            rx_len = 6;
            Response();

            addr = addr + FLASH_BASE_ADDR;
            FLASH_If_Write(addr, (uint32_t*)Page_Buf ,TGT_FLASH_PAGE_SIZE / 4);
            Flash_Key0 = 0;
            Flash_Key1 = 0;
            break;
/*     case 0x0B:      // 读取事件计数
            n = event_count > MAX_EVENT_COUNT ? MAX_EVENT_COUNT : event_count;
            *(ushort *)&uart0_buf[2] = from_little_endian_16(ps_server_busy ? 0xFFFF : server_status);
            *(ushort *)&uart0_buf[4] = from_little_endian_16(n);
            uart0_len = 6;
            Response();
            break;*/

       case 0x45:       // 失能写保护
            /* Disable the write protection */
            if (FLASH_If_WriteProtectionConfig(0) == HAL_OK)
            {
                rx_len = 2;
                Response();
            }
            else
            {
                Exception_Response(FLASH_WRITE_PROTECT_FAILURE);
            }
            break;
        case 0x46:
            if (FLASH_If_WriteProtectionConfig(1) == HAL_OK)
            {
                /* Launch the option byte loading */
                rx_len = 2;
                Response();
            }
            else
            {
                Exception_Response(FLASH_WRITE_PROTECT_FAILURE);
            }
            break;
        default:        // 不支持的指令代码
            Exception_Response(ILLEGAL_FUNCTION);
            break;
        }
          // 应答结束, 允许接收
        if (!REN0 && !uart0_tx_pending)
        {
            rx_len = 0;
            uart0_rx_pending = 0;
            REN0 = 1;
            usart_interrupt_enable(USART2, USART_INT_RBNE);
        }
    }


}


/**********************************************************/
// interrupt_callback
void HAL_UART_RxCpltCallback(UART_HandleTypeDef huart)
{
    if(huart == USART2)
    {
        if(!REN0)
            return;
        uart0_rx_pending = 1;
        if (timer_flag_get(TIMER3, TIMER_FLAG_CH0) == SET)
        {
            rx_len = 0;
        }
        uart0_timestamp = timer_counter_read(TIMER3) + 2000;
        timer_channel_output_pulse_value_config(TIMER3, TIMER_CH_0, uart0_timestamp);
        timer_flag_clear(TIMER3, TIMER_FLAG_CH0);
        rx_buf[rx_len++ & TGT_BL_BUF_SIZE_MASK] = (uchar)usart_data_receive(USART2);

        uart0_timestamp = timer_counter_read(TIMER3);
    }
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef huart)
{
    if(rx_len)
    {
        usart_data_transmit(USART2, *uart0_tx_ptr++);
        while(RESET == usart_interrupt_flag_get(USART2, USART_INT_FLAG_TBE));
        --rx_len;
    }
    else{
        uart0_tx_pending = 0;
        usart_interrupt_disable(USART2, USART_INT_TBE);
    }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef htim)
{
    if(htim == TIMER6) {
        ++system_tick.UU16;
    }
}
